﻿using System;
using System.Runtime.InteropServices;

namespace VisionCloud.Domain.File
{
    public enum SysOs
    {
        Unknown,
        Windows,
        Linux,
        OSX
    }

    public static class FileEncrypt
    {
        public static SysOs Platform { get; set; }

        static FileEncrypt()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                Platform = SysOs.Linux;
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                Platform = SysOs.OSX;
            }
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                Platform = SysOs.Windows;
            }
        }

        public static bool Encrypt(string OutFile, string InFile, string KeyStr)
        {
            switch (Platform)
            {
                case SysOs.Windows:
                    return FileEncryptForWindows.Encrypt(OutFile, InFile, KeyStr);

                case SysOs.Linux:
                    return FileEncryptForLinux.Encrypt(OutFile, InFile, KeyStr);

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        public static bool Decrypt(string OutFile, string InFile, string KeyStr)
        {
            switch (Platform)
            {
                case SysOs.Windows:
                    return FileEncryptForWindows.Decrypt(OutFile, InFile, KeyStr);

                case SysOs.Linux:
                    return FileEncryptForLinux.Decrypt(OutFile, InFile, KeyStr);

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        public static bool SpliceFile(string OutFile, string InFile, string Content, int Pos)
        {
            switch (Platform)
            {
                case SysOs.Windows:
                    return FileEncryptForWindows.spliceFile(OutFile, InFile, Content, Pos);

                case SysOs.Linux:
                    return FileEncryptForLinux.spliceFile(OutFile, InFile, Content, Pos);

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        public static bool SplitFile(string OutFile, string InFile, byte[] MD5, int Length, int Pos)
        {
            switch (Platform)
            {
                case SysOs.Windows:
                    return FileEncryptForWindows.splitFile(OutFile, InFile, MD5, Length, Pos);

                case SysOs.Linux:
                    return FileEncryptForLinux.splitFile(OutFile, InFile, MD5, Length, Pos);

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        public static void GetMD5(string InFile, byte[] MD5, bool IsFileMD5)
        {
            switch (Platform)
            {
                case SysOs.Windows:
                    FileEncryptForWindows.GetMD5(InFile, MD5, IsFileMD5);
                    break;

                case SysOs.Linux:
                    FileEncryptForLinux.GetMD5(InFile, MD5, IsFileMD5);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }

    public class FileEncryptForWindows
    {
        [DllImport("des.dll", EntryPoint = "Encrypt")]
        public static extern bool Encrypt(string OutFile, string InFile, string KeyStr);

        [DllImport("des.dll", EntryPoint = "Decrypt")]
        public static extern bool Decrypt(string OutFile, string InFile, string KeyStr);

        /// <summary>
        /// 拆分文件
        /// </summary>
        /// <param name="OutFile">输出路径</param>
        /// <param name="InFile">输入路径</param>
        /// <param name="Content">MD5</param>
        /// <param name="Pos">0:头部插入，1：末尾插入</param>
        /// <returns></returns>
        [DllImport("des.dll", EntryPoint = "spliceFile")]
        public static extern bool spliceFile(string OutFile, string InFile, string Content, int Pos);

        /// <summary>
        /// 拆分文件
        /// </summary>
        /// <param name="OutFile">输出路径</param>
        /// <param name="InFile">输入路径</param>
        /// <param name="MD5">MD5</param>
        /// <param name="Length"></param>
        /// <param name="Pos">0:头部插入，1：末尾插入</param>
        [DllImport("des.dll", EntryPoint = "splitFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool splitFile(string OutFile, string InFile, byte[] MD5, int Length, int Pos);

        /// <summary>
        /// 计算文件MD5值
        /// </summary>
        /// <param name="InFile">文件路径</param>
        /// <param name="IsFileMD5">计算本文件的MD5，1:是，2:否</param>
        /// <returns></returns>
        [DllImport("des.dll", EntryPoint = "GetMD5", CallingConvention = CallingConvention.Cdecl)]
        public static extern void GetMD5(string InFile, byte[] MD5, bool IsFileMD5);
    }

    public static class FileEncryptForLinux
    {
        [DllImport("libdes.so", EntryPoint = "Encrypt", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool Encrypt(string OutFile, string InFile, string KeyStr);

        [DllImport("libdes.so", EntryPoint = "Decrypt", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool Decrypt(string OutFile, string InFile, string KeyStr);

        /// <summary>
        /// 拆分文件
        /// </summary>
        /// <param name="outFile">输出路径</param>
        /// <param name="inFile">输入路径</param>
        /// <param name="content">MD5</param>
        /// <param name="pos">0:头部插入，1：末尾插入</param>
        /// <returns></returns>
        [DllImport("libdes.so", EntryPoint = "spliceFile", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool spliceFile(string outFile, string inFile, string content, int pos);

        /// <summary>
        /// 拆分文件
        /// </summary>
        /// <param name="OutFile">输出路径</param>
        /// <param name="InFile">输入路径</param>
        /// <param name="MD5">MD5</param>
        /// <param name="Length"></param>
        /// <param name="Pos">0:头部插入，1：末尾插入</param>
        [DllImport("libdes.so", EntryPoint = "splitFile")]
        public static extern bool splitFile(string OutFile, string InFile, byte[] MD5, int Length, int Pos);

        /// <summary>
        /// 计算文件MD5值
        /// </summary>
        /// <param name="InFile">文件路径</param>
        /// <param name="IsFileMD5">计算本文件的MD5，1:是，2:否</param>
        /// <returns></returns>
        [DllImport("libdes.so", EntryPoint = "GetMD5", CallingConvention = CallingConvention.Cdecl)]
        public static extern void GetMD5(string InFile, byte[] MD5, bool IsFileMD5);
    }
}